# Copyright 2018- The Pixie Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

load("@io_bazel_rules_docker//container:container.bzl", "container_image")
load("@io_bazel_rules_docker//docker/util:run.bzl", "container_run_and_extract")
load("//bazel:pl_build_system.bzl", "pl_cc_library", "pl_cc_test")

package(default_visibility = ["//src/stirling:__subpackages__"])

agent_files = [
    "Makefile.inner",
    "agent.cc",
    "raw_symbol_update.h",
]

# This is the header file where we will put the version hash
# of the Pixie Java symbolization JVMTI source files.
# The hash itself will replace the "{}" below.
_hash_dot_h_fmt = [
    "#pragma once",
    "#define PX_JVMTI_AGENT_HASH \"{}\"",
]

hash_dot_h_fmt = "\n".join(_hash_dot_h_fmt)

# These are the commands we use inside of the genrule to write agent_hash.h.
# $(SRCS) is the list of JVMTI source files, which the genrule picks up from agent_files.
# xargs is used to write the hash value in place of the "{}" inside hash_dot_h_fmt.
hash_cmds = [
    "cat $(SRCS)",
    "sha256sum",
    "head -c 32",
    "xargs -I{} echo '" + hash_dot_h_fmt + "'",
]

hash_cmd = " | ".join(hash_cmds)

# This writes the file "agent_hash.h".
genrule(
    name = "agent_hash",
    srcs = agent_files,
    outs = ["agent_hash.h"],
    cmd = hash_cmd + " > $@",
)

pl_cc_library(
    # This is a "header only" pl_cc_library: agent.cc is used to create a .so that will be injected
    # to a target Java process.
    name = "cc_headers",
    hdrs = glob(["*.h"]) + ["agent_hash.h"],
)

container_image(
    name = "image-glibc",
    base = "@openjdk-base-glibc//image",
    directory = "/build",
    files = agent_files + ["agent_hash.h"],
)

container_image(
    name = "image-musl",
    base = "@openjdk-base-musl//image",
    directory = "/build",
    files = agent_files + ["agent_hash.h"],
)

container_run_and_extract(
    name = "build-glibc",
    commands = [
        "apt-get update",
        "apt-get install -y lld",
        "apt-get install -y make",
        "apt-get install -y clang",
        "export INNER_JDK_PATH=/usr/local/openjdk-18",
        "make -C build -f Makefile.inner agent.so",
        "cp build/agent.so /lib-px-java-agent-glibc.so",
    ],
    extract_file = "/lib-px-java-agent-glibc.so",
    image = ":image-glibc.tar",
)

container_run_and_extract(
    name = "build-musl",
    commands = [
        "apk --no-cache add g++",
        "apk --no-cache add lld",
        "apk --no-cache add make",
        "apk --no-cache add clang",
        "export INNER_JDK_PATH=/opt/openjdk-18",
        "make -C build -f Makefile.inner agent.so",
        "cp build/agent.so /lib-px-java-agent-musl.so",
    ],
    extract_file = "/lib-px-java-agent-musl.so",
    image = ":image-musl.tar",
)

filegroup(
    name = "glibc",
    srcs = ["build-glibc/lib-px-java-agent-glibc.so"],
    visibility = [
        # Add visibility at top-level so that we can include
        # the lib in the pem image.
        "//:__pkg__",
        "//src/stirling:__subpackages__",
    ],
)

filegroup(
    name = "musl",
    srcs = ["build-musl/lib-px-java-agent-musl.so"],
    visibility = [
        # Add visibility at top-level so that we can include
        # the lib in the pem image.
        "//:__pkg__",
        "//src/stirling:__subpackages__",
    ],
)

pl_cc_test(
    name = "agent_test",
    srcs = [
        "agent_hash.h",
        "agent_test.cc",
    ],
    data = [
        ":glibc",
        "//src/stirling/source_connectors/perf_profiler/testing/java:fib_with_agent",
    ],
    tags = [
        "exclusive",
        "no_asan",
    ],
    deps = [
        ":cc_headers",
        "//src/common/exec:cc_library",
        "//src/common/fs:cc_library",
        "//src/stirling/testing:cc_library",
    ],
)
